<!-- 麦克风 -->
<template>
	<div class="pannel">
		<audio id="mp3-data-url"></audio>
		<div class="cardbox flex flex-v flex-pack-center">
			<div v-if="operateType == 'nostart'">
				<div
					class="fixed-save-btn"
					:class="{ official: isPro }"
					v-if="operateType == 'nostart' && !(isAnswering - 0)"
					@click="startAnswer"
				>
					开始
				</div>
				<!-- <div class="myForm" style="background: #fff; padding: 30px 0; border-radius: 10px">
					<div class="form-con flex flex-align-center" style="margin-right: 80px">
						<div>
							<div class="form-item flex flex-align-center">
								<label class="ant-form-item-required">麦克风类型</label>
								<div class="my-input" style="overflow: visible; padding-top: 5px">
									<a-radio-group v-model="microphoneType" @change="handleMicrophoneType">
										<a-radio :value="1">抢麦</a-radio>
										<a-radio :value="2">自由麦</a-radio>
									</a-radio-group>
								</div>
							</div>
						</div>
					</div>
				</div> -->
			</div>
			<div class="answer" v-else>
				<div class="music">
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
					<div class="bar"></div>
				</div>
				<div class="namebar" v-if="curuID">
					<img src="/audio/ht.png" alt="" />
					<div class="name">{{ curStudent.studName || '' }}</div>
				</div>
				<div style="height: 75px" v-else></div>
				<div class="save-btn" @click="stopAnswer">结束</div>
			</div>
		</div>
		<div class="topicType">
			<img :src="`/impromptu${isPro ? '_pro' : ''}/topicType.png`" class="img" />
			<span class="name">麦克风</span>
		</div>
	</div>
</template>

<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';
import bus from '@/utils/eventBus';
import { debounce, getBytesLength, base64ToBlob, dataURLtoBlob } from '@/utils/base.js';
let timer = null;
function mergeBase64MP3s(base64MP3s) {
	// 将Base64字符串转换为二进制数据
	const b64toBlob = (b64data, contentType = '', sliceSize = 512) => {
		const byteCharacters = atob(b64data);
		const byteArrays = [];

		for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
			const slice = byteCharacters.slice(offset, offset + sliceSize);
			const byteNumbers = new Array(slice.length);
			for (let i = 0; i < slice.length; i++) {
				byteNumbers[i] = slice.charCodeAt(i);
			}
			const byteArray = new Uint8Array(byteNumbers);
			byteArrays.push(byteArray);
		}

		return new Blob(byteArrays, { type: contentType });
	};

	// 创建一个新的Blob来存储合并后的MP3
	let list = [];
	base64MP3s.forEach((item) => {
		list.push(b64toBlob(item));
	});
	const mergedBlob = new Blob(list, { type: 'audio/mp3' });

	// 将Blob转换回Base64编码
	const blobToBase64 = (blob, callback) => {
		const reader = new FileReader();
		reader.onload = function (e) {
			callback(e.target.result);
		};
		reader.readAsDataURL(blob);
	};

	return new Promise((resolve, reject) => {
		blobToBase64(mergedBlob, (base64Result) => {
			resolve(mergedBlob);
		});
	});
}
function mergeBase64SPXs(base64SPXs) {
	// 将Base64字符串转换为二进制数据
	const b64toBlob = (b64data, contentType = '', sliceSize = 512) => {
		const byteCharacters = atob(b64data);
		const byteArrays = [];

		for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
			const slice = byteCharacters.slice(offset, offset + sliceSize);
			const byteNumbers = new Array(slice.length);
			for (let i = 0; i < slice.length; i++) {
				byteNumbers[i] = slice.charCodeAt(i);
			}
			const byteArray = new Uint8Array(byteNumbers);
			byteArrays.push(byteArray);
		}

		return new Blob(byteArrays, { type: contentType });
	};

	function decodeFile(bufSpx) {
		var stream, samples, st;
		var ogg, header, err;
		ogg = new Ogg(bufSpx, { file: true });

		console.log('bufSpx1', ogg, bufSpx);
		ogg.demux();
		stream = ogg.bitstream();
		console.log('bufSpx2', stream);
		header = Speex.parseHeader(ogg.frames[0]);
		console.log(header);

		comment = new SpeexComment(ogg.frames[1]);
		console.log(comment.data);

		st = new Speex({
			quality: 8,
			mode: header.mode,
			rate: header.rate,
		});

		samples = st.decode(stream, ogg.segments);

		var waveData = PCMData.encode({
			sampleRate: header.rate,
			channelCount: header.nb_channels,
			bytesPerSample: 2,
			data: samples,
		});

		// array buffer holding audio data in wav codec
		var bufWav = Speex.util.str2ab(waveData);
		// // convert to a blob object
		// var blob = new Blob([bufWav], { type: 'audio/wav' });
		// // return a "blob://" url which can be used as a href anywhere
		// return URL.createObjectURL(blob);
		return bufWav;
	}
	// 创建一个新的Blob来存储合并后的MP3
	let list = [];
	base64SPXs.forEach((item) => {
		list.push(b64toBlob(item));
	});
	const mergedBlob = new Blob(list, { type: 'audio/mp3' });

	// 将Blob转换回Base64编码
	const blobToBase64 = (blob, callback) => {
		const reader = new FileReader();
		reader.onload = function (e) {
			callback(e.target.result);
		};
		reader.readAsDataURL(blob);
	};
	const blobToArrayBuffer = (blob, callback) => {
		let reader = new FileReader();
		reader.onload = function () {
			return callback(this.result);
		};
		reader.readAsArrayBuffer(blob);
		return reader;
	};
	let ss = decodeFile(blobToArrayBuffer(mergedBlob));
	return new Promise((resolve, reject) => {
		var blobss = new Blob([ss], { type: 'audio/wav' });
		resolve(blobss);
	});
}
let timerPlay = null;
export default {
	name: 'praise',
	components: {},
	props: {
		//接收器信息
		machineData: {
			type: Object,
			default: () => {},
		},
		//表单数据
		formData: {
			type: Object,
			default: () => {},
		},
	},
	data() {
		return {
			csId: '',
			classId: '',
			microphoneType: 2,
			operateType: 'nostart', //组件页面类型
			ans_id: '',
			audioList: [],
			curIndex: -1,
			curuID: '', //当前抢到麦的学生
			audioContext: null,
			audioDataQueue: [],
			audioBuffer1: null,
			audioBuffer2: null,
			currentBufferIndex: 0,
		};
	},
	created() {
		let beginClassData = this.$ls.get('beginClass'); //上课数据
		this.csId = beginClassData.csId;
		this.classId = beginClassData.classId;
		// this.ans_id = sessionStorage.getItem('ans_id');
	},
	mounted() {
		this.audioContext = new AudioContext();
	},
	watch: {
		//有线设备上报答题数据
		wiredAnswer: {
			handler(newValue, oldValue) {
				if (newValue && newValue != oldValue) {
					console.log('答题器');
					let beginClassData = this.$ls.get('beginClass');
					if (this.curuID) {
						//如果有学生已经抢到麦克风，怎不再处理
						return;
					}
					if (beginClassData && JSON.stringify(beginClassData) != '{}' && beginClassData.topicType != 99) {
						let uID = newValue.uID - 0;
						let stuInfo = this.studentList.find((item) => item.machineId - 0 == uID);
						this.ans_id = sessionStorage.getItem('ans_id');
						console.log('答题2', this.ans_id, newValue.ans_id, newValue.ans_str);

						if (this.ans_id && this.ans_id == newValue.ans_id && newValue.ans_str == 'G') {
							this.curuID = uID;
							console.log('答题3');
							//结束题目，单独发送语音题
							this.WEBSOCKET_SEND({
								fun: 'answer_start',
								uID: 0,
								type: 128, //结束答题
							});
							this.studentList.forEach((item) => {
								console.log('item', item);
								if (item.status == 1) {
									let msg = '   ' + item.studName;
									let len = 16 - getBytesLength(msg);
									for (var i = 0; i < len; i++) {
										msg = msg + ' ';
									}
									if (item.machineId - 0 == uID) {
										msg = msg + '长按语音键发言';
										timer = setTimeout(() => {
											this.WEBSOCKET_SEND({
												fun: 'answer_start',
												uID: uID,
												type: 8,
											});
										}, 50);
									} else {
										msg = msg + '   已有人发言';
									}
									this.WEBSOCKET_SEND({
										fun: 'dtq_echo_set',
										uID: item.machineId - 0,
										msg: msg,
									});
								}
							});
						}
					}
				}
			},
			immediate: true, //初始化时让handler调用一下
			deep: true, // 开启深度监听
		},
		voiceStream: {
			handler(newValue, oldValue) {
				if (newValue && JSON.stringify(newValue) != JSON.stringify(oldValue)) {
					if (newValue.pac_num == 1) {
						this.audioList = [];
					}
					if (newValue.voice_data) {
						this.audioList.push(newValue);
					}
					if (newValue.pac_flg == 1) {
						let base64MP3s = this.audioList.map((item) => {
							return item.voice_data;
						});
						console.log('base64MP3s', base64MP3s);
						mergeBase64MP3s(base64MP3s).then((mergedBlob) => {
							// 处理合并后的Base64编码的MP3
							let audioObj = document.getElementById('mp3-data-url');
							audioObj.src = window.URL.createObjectURL(mergedBlob);
							audioObj.play();
							audioObj.addEventListener('canplay', () => {
								window.URL.revokeObjectURL(audioObj.src);
							});
						});
					}
				}
			},
			immediate: true, //初始化时让handler调用一下
			deep: true, // 开启深度监听
		},
	},
	computed: {
		...mapState({
			deviceType: (state) => state.websockStore.deviceType,
			studentList: (state) => state.websockStore.studentList,
			isPro: (state) => state.isPro,
			stopDeviceEventList: (state) => state.websockStore.stopDeviceEventList,
			minProjectLogin: (state) => state.minProjectStore.minProjectLogin, //小程序是否登录
			isAnswering: (state) => state.websockStore.isAnswering,
		}),
		wiredAnswer() {
			return this.$store.getters.onEvent('wiredanswer');
		},
		voiceStream() {
			return this.$store.getters.onEvent('voice_stream');
		},
		voiceUpdate() {
			return this.$store.getters.onEvent('voice_update');
		},
		curStudent() {
			if (this.curuID) {
				return this.studentList.find((item) => item.machineId - 0 == this.curuID);
			}
			return '';
		},
	},

	methods: {
		...mapMutations(['WEBSOCKET_SEND', 'SET_studentList', 'SET_STOPDEVICEEVENTLIST']),
		handleMicrophoneType(e) {
			this.microphoneType = e.target.value;
		},
		//去答题
		startAnswer() {
			this.curuID = '';
			/* 判断移动端正在控制PC端 */
			if (this.minProjectLogin) {
				this.$message.error('移动端正在控制PC端，不能发题！');
				return;
			}
			//发题前判断该班级是否有学生。
			if (this.studentList.length == 0) {
				let tempTestData = this.$ls.get('tempTestData');
				this.$message.error('（' + tempTestData.className + '）班级没有学生，请先添加学生！');
				return;
			}
			this.sendStartAnswer();
		},
		sendStartAnswer() {
			if (this.microphoneType == 1) {
				this.WEBSOCKET_SEND({
					fun: 'answer_start',
					uID: 0,
					type: 6,
				});
				console.log('this.studentList', this.studentList);
				this.studentList.forEach((item) => {
					console.log('item', item);
					if (item.status == 1) {
						let space = [];
						let msg = '   ' + item.studName;
						let len = 16 - getBytesLength(msg);
						for (var i = 0; i < len; i++) {
							msg = msg + ' ';
						}
						msg = msg + '   请按语音键';
						this.WEBSOCKET_SEND({
							fun: 'dtq_echo_set',
							uID: item.machineId - 0,
							msg: msg,
						});
					}
				});
			} else {
				this.WEBSOCKET_SEND({
					fun: 'answer_start',
					uID: 0,
					type: 8,
				});
				this.studentList.forEach((item) => {
					console.log('item', item);
					if (item.status == 1) {
						let msg = '   ' + item.studName;
						let len = 16 - getBytesLength(msg);
						for (var i = 0; i < len; i++) {
							msg = msg + ' ';
						}
						msg = msg + '长按语音键发言';
						this.WEBSOCKET_SEND({
							fun: 'dtq_echo_set',
							uID: item.machineId - 0,
							msg: msg,
						});
					}
				});
			}
			this.operateType = 'answer';
		},

		stopAnswer() {
			this.WEBSOCKET_SEND({
				fun: 'answer_start',
				uID: 0,
				type: 128, //结束答题
			});
			this.studentList.forEach((item) => {
				if (item.status == 1) {
					let msg = '   ' + item.studName;
					this.WEBSOCKET_SEND({
						fun: 'dtq_echo_set',
						uID: item.machineId - 0,
						msg: msg,
					});
				}
			});
			this.audioList = [];
			this.curIndex = -1;
			this.curuID = '';
			this.operateType = 'nostart';
		},
		playAudioBuffer() {
			if (this.audioContext) {
				const bufferToPlay = this.currentBufferIndex === 0 ? this.audioBuffer1 : this.audioBuffer2;
				if (bufferToPlay) {
					const audioBufferSource = this.audioContext.createBufferSource();
					audioBufferSource.buffer = bufferToPlay;
					audioBufferSource.connect(this.audioContext.destination);
					audioBufferSource.start();
					this.currentBufferIndex = 1 - this.currentBufferIndex;
				}
			}
		},
	},
};
</script>

<style lang="less" scoped>
.pannel {
	position: relative;
	width: 1162px;
	margin: 0 auto;
	height: 100%;
	// padding: 50px 0 30px;
	@media screen and (max-width: 1366px) {
		width: 1024px;
	}
	.music {
		width: 300px;
		height: 200px;
		position: relative;
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin: -100px auto 0;
	}
	.music .bar {
		width: 8px;
		border-radius: 10px;
		background: @primary-color;
		animation: movement 1.5s ease-in-out infinite;
	}
	.music .bar:nth-child(1) {
		animation-delay: 1s;
	}
	.music .bar:nth-child(2) {
		animation-delay: 0.8s;
	}
	.music .bar:nth-child(3) {
		animation-delay: 0.6s;
	}
	.music .bar:nth-child(4) {
		animation-delay: 0.4s;
	}
	.music .bar:nth-child(5) {
		animation-delay: 0.2s;
	}
	.music .bar:nth-child(6) {
		animation-delay: 0.2s;
	}
	.music .bar:nth-child(7) {
		animation-delay: 0.4s;
	}
	.music .bar:nth-child(8) {
		animation-delay: 0.6s;
	}
	.music .bar:nth-child(9) {
		animation-delay: 0.8s;
	}
	.music .bar:nth-child(10) {
		animation-delay: 1s;
	}
	.music .bar:nth-child(11) {
		animation-delay: 1s;
	}
	.music .bar:nth-child(12) {
		animation-delay: 0.8s;
	}
	.music .bar:nth-child(13) {
		animation-delay: 0.6s;
	}
	.music .bar:nth-child(14) {
		animation-delay: 0.4s;
	}
	.music .bar:nth-child(15) {
		animation-delay: 0.2s;
	}
	.namebar {
		position: relative;
		background: @primary-color;
		border-radius: 50px;
		width: 300px;
		height: 75px;
		text-align: center;
		color: #fff;
		font-size: 41px;
		font-weight: 600;
		padding-left: 50px;
		line-height: 75px;
		margin: 30px auto;
	}
	.namebar img {
		position: absolute;
		left: -20px;
		bottom: -10px;
		width: 122px;
		height: 122px;
	}
	.save-btn {
		background: @primary-color;
		width: 300px;
		height: 60px;
		line-height: 60px;
		border-radius: 40px;
		text-align: center;
		color: #fff;
		font-size: 30px;
		cursor: pointer;
		margin: 20px auto;
		position: absolute;
		bottom: 100px;
		left: 50%;
		transform: translateX(-50%);
		&.small {
			width: 100px;
			height: 40px;
			line-height: 40px;
			font-size: 18px;
			margin: 20px auto;
		}
		&:hover {
			background: rgba(0, 190, 197, 0.5);
		}
		&.official:hover {
			background: rgba(86, 151, 245, 0.5);
		}
	}
}
/* **头部题目类型** */
.topicType {
	width: 304px;
	height: 100px;
	line-height: 100px;
	position: fixed;
	top: 0;
	left: 49px;
	z-index: 7;
	.img {
		width: 304px;
		height: 100px;
		position: absolute;
		right: 0;
	}
	.name {
		position: absolute;
		top: 70%;
		left: 50%;
		transform: translate(-50%, -50%);
		font-size: 30px;
		color: #fff;
	}
	@media screen and (max-width: 1366px) {
		width: 254px;
		height: 80px;
		line-height: 80px;
		.img {
			width: 254px;
			height: 80px;
		}
		.name {
			font-size: 28px;
		}
	}
}
.cardbox {
	overflow: visible;
	height: 100%;
	position: relative;
	margin-top: 0;
	padding-top: 15px;
}
.cardbox .closeWin {
	position: absolute;
	right: -20px;
	bottom: -16px;
	width: 46px;
	height: 46px;
	img {
		display: block;
		width: 100%;
		height: 100%;
	}
}

.fixed-save-btn {
	background: @primary-color;
	width: 247px;
	height: 40px;
	line-height: 40px;
	border-radius: 40px;
	text-align: center;
	color: #fff;
	font-size: 20px;
	font-weight: bold;
	cursor: pointer;
	position: fixed;
	bottom: 60px;
	right: 180px;
	z-index: 9;
	&:hover {
		background: rgba(0, 190, 197, 0.5);
	}
	&.official:hover {
		background: rgba(86, 151, 245, 0.5);
	}
	@media screen and (max-width: 1366px) {
		width: 227px;
	}
}
</style>

<style>
@keyframes movement {
	0%,
	100% {
		height: 2px;
	}
	50% {
		height: 80px;
	}
}
</style>
